package ueb15;

import ueb15.Controller;

import ueb15.RedBlackTreeGui;



import java.awt.Component;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.concurrent.ExecutionException;

import javax.swing.SwingWorker;
import ueb15.PaintableRedBlackTreeImpl;


/**
 * Controller as of the Model-View-Controller-Paradigm.
 */
public class GuiController implements Controller {

	private abstract class TreeCaller extends SwingWorker<Void, Void> {
		@Override
		public void done() {
			try {
				// exceptions are swallowed unless following method is called
				get();
			} catch (InterruptedException exc) {
				// let Swing/AWT handle this
				Thread.currentThread().interrupt();
			} catch (ExecutionException exc) {
				System.out.println("Some Exception occured in background, exiting.");
				if (exc.getCause() != null) {
					exc.getCause().printStackTrace();
				} else {
					exc.printStackTrace();
				}
				stopGui();
			}
		}
	}

	public static void main(String[] args) {
		javax.swing.SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				new GuiController().startGui();
			}
		});
	}

	private final RedBlackTreeGui gui;
	private PaintableRedBlackTreeImpl tree;

	private final RedBlackTreeComponent view;

	public GuiController() {
		Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
			@Override
			public void uncaughtException(Thread t, Throwable e) {
				System.out.println("Some Exception occured in thread " + t.getName() + ", exiting.");
				e.printStackTrace();
				stopGui();
			}
		});
		tree = new PaintableRedBlackTreeImpl(this);
		view = new RedBlackTreeComponent(this);
		gui = new RedBlackTreeGui(this);
	}

	@Override
	public void addValue(final Object input) {
		System.out.println("Adding node with value " + input + ".");
		new TreeCaller() {
			@Override
			public Void doInBackground() {
				tree.insertValue(input);
				return null;
			}
		}.execute();
	}

	@Override
	public RedBlackTreeGui getGui() {
		return gui;
	}

        @Override
	public PaintableRedBlackTreeImpl getTree() {
		return tree;
	}

	@Override
	public Component getView() {
		return view;
	}

	@Override
	public void restart() {
		System.out.println("Restarting...");
		tree = new PaintableRedBlackTreeImpl(this);
		updateGui();
	}

	@Override
	public void startGui() {
		javax.swing.SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				System.out.println("Starting application.");
				gui.showGui();
			}
		});
	}

	@Override
	public void stopGui() {
		System.out.println("Stopping application: Thanks for usage!");
		// we have nothing to cleanup
		System.exit(0);
	}

	@Override
	public void updateGui() {
		javax.swing.SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				view.repaint();
			}
		});
	}
}
